/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package control;

import VO.TransactionResult;
import co.edu.unal.satacredito.database.connection.TransactionDatastoreFactory;
import co.edu.unal.satacredito.database.constants.FileLogConstants;
import co.edu.unal.satacredito.database.constants.TransactionConstants;
import co.edu.unal.satacredito.database.dao.FileLogMongoDao;
import co.edu.unal.satacredito.database.dao.TransactionMongoDao;
import co.edu.unal.satacredito.database.entity.FileLog;
import co.edu.unal.satacredito.database.entity.Transaction;
import co.edu.unal.satacredito.database.exception.UnreachableHostException;
import com.google.code.morphia.Datastore;
import com.mongodb.MongoException;
import entity.Singleton;
import java.net.UnknownHostException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bson.types.ObjectId;

/**
 *
 * @author julianDavidPG
 */
public class TransactionStateControl {
    
    private static Singleton singleton;
    
    private static final int SENT_TO_CLIENT = 2;

    public TransactionStateControl() {
        singleton = Singleton.getInstance();
    }
    
    public List<TransactionResult> getTransactionResultByEstablishment(String fileId) {
        List<TransactionResult> statesToSend = new ArrayList<TransactionResult>();
        List<TransactionResult> states = singleton.getStates();
        Iterator it = states.iterator();
        while (it.hasNext()) {
            TransactionResult result = (TransactionResult) it.next();
            if(result.getFileId().equals(fileId)){
                statesToSend.add(result);
                it.remove();
            }
        }
        for (TransactionResult t : states) {
            if(t.getFileId().equals(fileId)){
                int index = states.indexOf(t);
                statesToSend.add(states.remove(index));
            }
        }
        return statesToSend;
    }

    public void startRevision(final String fileId) {
        try {
            Datastore datastore = TransactionDatastoreFactory.createDatastore();
            final ObjectId id = new ObjectId(fileId);
            final FileLogMongoDao fdao = new FileLogMongoDao(datastore);
            final TransactionMongoDao tdao = new TransactionMongoDao(datastore);
            boolean fileFinished = false;
            while (!fileFinished) {
                List<Transaction> transactions = null;
                try {
                    transactions = tdao.findSemanticReadedByFileId(id);
                } catch (UnreachableHostException ex) {
                    Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error trying to execute rdao.findTransactionsNotReadedByEstablishment(id)", ex);
                    return;
                }
                List<TransactionResult> states = singleton.getStates();
                try {
                    for (Transaction transaction : transactions) {
                        transaction.setReadState(TransactionStateControl.SENT_TO_CLIENT);
                        tdao.update(transaction.getTransactionId(), transaction);
                        states.add(transactionToTransactionState(transaction,fileId));
                    }
                } catch (UnreachableHostException unreachableHostException) {  
                    Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error trying to execute tdao.update(id, transaction)", unreachableHostException);
                    return;
                }
                try {
                    Thread.sleep(5000l);
                } catch (InterruptedException ex) {
                    Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error executing Thread.sleep(5000l)", ex);
                    return;
                }
                fileFinished = fileFinished(id,fdao);
                System.out.println("file finished: " + fileFinished);
            }
        } catch (UnknownHostException ex) {
            Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MongoException ex) {
            Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private TransactionResult transactionToTransactionState(Transaction transaction, String fileId) {
        TransactionResult state = new TransactionResult();
//        state.setLineNumber(transaction.getLineNumber());
        state.setTransactionId(transaction.getTransactionId().toString());
        state.setValidationResult(transaction.getValidationResult());
        state.setResultIssue(transaction.getValidationIssue());
        state.setFileId(fileId);
        return state;
    }
    
    public boolean insert() {
        Datastore datastore;
        try {
            datastore = TransactionDatastoreFactory.createDatastore();
        } catch (UnknownHostException ex) {
            Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error executing datastore = TransactionMongoConnection.getTransactionConnection()", ex);
            return false;
        } catch (MongoException ex) {
            Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error executing datastore = TransactionMongoConnection.getTransactionConnection()", ex);
            return false;
        }
        final TransactionMongoDao tdao = new TransactionMongoDao(datastore);
        ObjectId file1 = new ObjectId();
        System.out.println("file1: "+ file1.toString());
        ObjectId file2 = new ObjectId();
        System.out.println("file2: "+ file2.toString());
        ObjectId franchise1 = new ObjectId();
        ObjectId franchise2 = new ObjectId();
        Date date = new Date();
        for (int i = 0; i < 5000; i++) {
            Transaction transaction4 = new Transaction();
            if (i%2 == 0) {
                transaction4.setFileId(file1);
            } else {
                transaction4.setFileId(file2);
            }
            transaction4.setName("Name"+i);
            transaction4.setNin(String.valueOf(40000000000l +i));
            transaction4.setNinType(TransactionConstants.NIN_PASSPORT);
            transaction4.setCardNumber(String.valueOf(30303030000l +i));
            if (i%2 == 0) {
                transaction4.setCardType(TransactionConstants.CARD_DEBIT);
            } else {
                transaction4.setCardType(TransactionConstants.CARD_CREDIT);
            }
            if (i%5 == 0) {
                transaction4.setFranchise(franchise1);
            } else {
                transaction4.setFranchise(franchise2);
            }
            transaction4.setPurchaseDate(date);
            transaction4.setPurchaseAmount(40000l);
            transaction4.setPurchaseDetail("Compra bla, bla, bla...");
            transaction4.setValidationDate(date);
            if (i%4 == 0) {
                transaction4.setValidationResult(TransactionConstants.RESULT_FAILED);
                if (i%3 == 0) {
                    transaction4.setValidationIssue(TransactionConstants.ISSUE_NIN);
                } else {
                    transaction4.setValidationIssue(TransactionConstants.ISSUE_CARD);
                }
            } else {
                transaction4.setValidationResult(TransactionConstants.RESULT_APPROVED);
            }
            if (i%60 == 0) {
                transaction4.setReadState(TransactionConstants.READ_CLIENT);
            } else {
                transaction4.setReadState(TransactionConstants.READ_SEMANTIC);
            }
            try {
                tdao.create(transaction4);
            } catch (UnreachableHostException ex) {
                Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error executing tdao.create(transaction4)", ex);
                return false;
            }
        }
        return true;
    }
    
    private boolean fileFinished(ObjectId fileId, FileLogMongoDao fdao) {
        try {
            FileLog state = fdao.findByFileId(fileId);
            if (state.getState() == FileLogConstants.STATE_END) {
                return true;
            } else {
                return false;
            }
        } catch (UnreachableHostException unreachableHostException) {
            Logger.getLogger(TransactionStateControl.class.getName()).log(Level.SEVERE, "error trying to execute fdao.findByFile(fileId)", unreachableHostException);
            return true;
        }
    }
}
